#[allow(clippy::vec_init_then_push)]
#[allow(clippy::useless_vec)]
fn main() {
    {
        let name1 = String::from("Windy");
        let name2 = String::from("Gomesy");

        let mut my_vec = Vec::new();
        // If we run the program now, the compiler will give an error.
        // It doesn't know the type of vec.

        // Now it knows: it's Vec<String>.
        my_vec.push(name1);
        my_vec.push(name2);
        dbg!(&my_vec);
    }

    println!();

    {
        let name1 = String::from("Windy");
        let name2 = String::from("Gomesy");

        // The compiler knows the type so there is no error.
        let mut my_vec: Vec<String> = Vec::new();
        my_vec.push(name1);
        my_vec.push(name2);
        dbg!(&my_vec);
    }

    println!();

    {
        let my_vec = vec![8, 10, 10];
        dbg!(&my_vec);
    }

    println!();

    {
        let vec_of_ten = vec![1, 2, 3, 4, 5, 6, 7, 8, 9, 10];
        // Everything is the same as above except we added vec!.
        let three_to_five = &vec_of_ten[2..5];
        let start_at_two = &vec_of_ten[1..];
        let end_at_five = &vec_of_ten[..5];
        let everything = &vec_of_ten[..];

        println!(
            "Three to five: {:?},
start at two: {:?}
end at five: {:?}
everything: {:?}",
            three_to_five, start_at_two, end_at_five, everything
        );
    }

    println!();

    {
        let mut num_vec = Vec::new();
        // 0 elements: prints 0.
        println!("{}", num_vec.capacity());
        // Add one character.
        num_vec.push('a');
        // 1 element: prints 4. Vecs with 1 item always start with capacity 4.
        println!("{}", num_vec.capacity());
        // Add one more.
        num_vec.push('a');
        // Add one more.
        num_vec.push('a');
        // Add one more.
        num_vec.push('a');
        // 4 elements: still prints 4.
        println!("{}", num_vec.capacity());
        // Add one more.
        num_vec.push('a');
        // Prints 8. We have 5 elements, but it doubled 4 to 8 to make space.
        println!("{}", num_vec.capacity());
    }

    println!();

    // So this vector has two reallocations: 0 to 4, and 4 to 8. We can make it
    // faster.
    {
        // Give it capacity 8.
        let mut num_vec = Vec::with_capacity(8);
        // Add one character.
        num_vec.push('a');
        // Prints 8.
        println!("{}", num_vec.capacity());
        // Add one more.
        num_vec.push('a');
        // Prints 8.
        println!("{}", num_vec.capacity());
        // Add one more.
        num_vec.push('a');
        // Prints 8.
        println!("{}", num_vec.capacity());
        // Add one more.
        num_vec.push('a');
        // Add one more.
        num_vec.push('a');
        // Now we have 5 elements.
        // Still 8.
        println!("{}", num_vec.capacity());

        // This vector has 0 reallocations, which is better. So if you think you
        // know how many elements you need, you can use Vec::with_capacity()
        // to make it faster.
    }

    println!();

    {
        // You remember that you can use .into() to make a &str into a String.
        // You can also use it to make an array into a Vec. You have to tell
        // .into() that you want a Vec, but you don't have to choose the type
        // of Vec. If you don't want to choose, you can write Vec<_>.
        let my_vec1: Vec<u8> = [1, 2, 3].into();
        dbg!(&my_vec1);

        // Vec<_> means "choose the Vec type for me".
        // Rust will choose Vec<i32>.
        let my_vec2: Vec<_> = [9, 0, 10].into();
        dbg!(&my_vec2);
    }
}
